import TreeCesiumData from "./layer_tree_data";
import Environment from "../../utils/environment";
import LayerManager from "@/plugins/mev/layer/LayerManager";
import axios from "axios"
import * as Cesium from "cesium";

class VectorData extends TreeCesiumData {
    constructor(data, viewer) {
        super(data, viewer);
        this._data = data;
        this._viewer = viewer;
        this._dataObjectPolyLine = null;
        this._dataObjectPolygon = null;
        this._rect = null;
    }

    show() {
        let options = this._data.options;
        const color = options.color !== undefined ? Cesium.Color.fromCssColorString(options.color) : Cesium.Color.fromBytes(255, 255, 255, 255);
        const lineWidth = options.lineWidth !== undefined ?  options.lineWidth : 4;
        const transparent = color.alpha < 1.0;
        axios.get(this._data.basePath + this._data.path + "?datatype=json").then(response => {
                let json = response.data;
                let polylineInstances = [];
                let polygonInstances = [];
                let rect = new Cesium.Rectangle(180, 90, -180, -90);
                rect.east = -180;
                rect.west = 180;
                rect.south = 90;
                rect.north = -90;
                json.features.forEach(feature => {
                    if (feature.geometry !== undefined && feature.geometry !== null) {
                        if (feature.geometry.type === "LineString") {
                            let instance = this.createPolylineInstanceFromCoordinates(feature.geometry.coordinates, lineWidth);
                            this.calculateExtent(feature.geometry.coordinates, rect);
                            polylineInstances.push(instance);
                        } //LineString
                        else if (feature.geometry.type === "MultiLineString") {
                            for (let i = 0; i < feature.geometry.coordinates.length; ++i) {
                                let instance = this.createPolylineInstanceFromCoordinates(feature.geometry.coordinates[i], lineWidth);
                                polylineInstances.push(instance);
                            }
                            this.calculateExtent(feature.geometry.coordinates, rect);
                        } // MultiLineString
                        else if (feature.geometry.type === "Polygon") {
                            let instance = this.createPolygonInstanceFromCoordinates(feature.geometry.coordinates);
                            this.calculateExtent(feature.geometry.coordinates, rect);
                            polygonInstances.push(instance);
                        } // Polygon
                        else if (feature.geometry.type === "MultiPolygon") {
                            for (let i = 0; i < feature.geometry.coordinates.length; ++i) {
                                let instance = this.createPolygonInstanceFromCoordinates(feature.geometry.coordinates[i]);
                                polygonInstances.push(instance);
                            }
                            this.calculateExtent(feature.geometry.coordinates, rect);
                        } // MultiPolygon
                    }

                }); // Per feature

                this._rect = new Cesium.Rectangle(Cesium.Math.toRadians(rect.west), Cesium.Math.toRadians(rect.south), Cesium.Math.toRadians(rect.east), Cesium.Math.toRadians(rect.north));
                if (polylineInstances.length != 0) {
                    let polylineMaterial = Cesium.Material.fromType('Color');
                    polylineMaterial.uniforms.color = color;
                    this._dataObjectPolyLine = new Cesium.GroundPolylinePrimitive({
                        geometryInstances: polylineInstances,
                        appearance: new Cesium.EllipsoidSurfaceAppearance({
                            material: polylineMaterial,
                            translucent: transparent
                        })
                    });
                    this._viewer.scene.groundPrimitives.add(this._dataObjectPolyLine);
                }
                if (polygonInstances.length != 0) {
                    let polygonMaterial = Cesium.Material.fromType('Color');
                    polygonMaterial.uniforms.color = color;
                    this._dataObjectPolygon = new Cesium.GroundPrimitive({
                        geometryInstances: polygonInstances,
                        appearance: new Cesium.EllipsoidSurfaceAppearance({
                            material: polygonMaterial,
                            translucent: transparent
                        })
                    });
                    this._viewer.scene.groundPrimitives.add(this._dataObjectPolygon);
                }
            }
        );

    }


    close() {
        if (this._dataObjectPolyLine) {
            if (this._viewer.scene.groundPrimitives.contains(this._dataObjectPolyLine)) {
                this._viewer.scene.groundPrimitives.remove(this._dataObjectPolyLine);
            }
            this._dataObjectPolyLine = null;
        }
        if (this._dataObjectPolygon) {
            if (this._viewer.scene.groundPrimitives.contains(this._dataObjectPolygon)) {
                this._viewer.scene.groundPrimitives.remove(this._dataObjectPolygon);
            }
            this._dataObjectPolygon = null;
        }
        this._rect = null;
    }

    flyTo() {
        if (this._rect !== null) {
            this._viewer.camera.flyTo({
                destination: this._rect
            });
        }
    }

    createPolylineInstanceFromCoordinates(coordinates, lineWidth) {
        let vertices = new Array(coordinates.length * 2);
        for (let i = 0; i < coordinates.length; ++i) {
            vertices[i * 2] = coordinates[i][0];
            vertices[i * 2 + 1] = coordinates[i][1];
        }
        return new Cesium.GeometryInstance({
            geometry: new Cesium.GroundPolylineGeometry({
                positions: Cesium.Cartesian3.fromDegreesArray(vertices),
                width: lineWidth
            })
        });
    }

    createPolygonInstanceFromCoordinates(coordinates) {
        let holes = [];
        let positions = [];
        for (let i = 0; i < coordinates.length; ++i) {
            let vertices = new Array(coordinates[i].length * 2);
            for (let j = 0; j < coordinates[i].length; ++j) {
                vertices[j * 2] = coordinates[i][j][0];
                vertices[j * 2 + 1] = coordinates[i][j][1];
            }
            if (i === 0) {
                positions = Cesium.Cartesian3.fromDegreesArray(vertices);
            } else {
                holes.push(new Cesium.PolygonHierarchy(
                    Cesium.Cartesian3.fromDegreesArray(vertices)
                ));
            }
        }
        let polygon = new Cesium.PolygonGeometry({
            polygonHierarchy: new Cesium.PolygonHierarchy(positions, holes),
            vertexFormat: Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT
        });
        return new Cesium.GeometryInstance({geometry: polygon});
    }

    calculateExtent(coordinates, rect) {
        if (Array.isArray(coordinates) && !Array.isArray(coordinates[0])) {
            if (coordinates[0] < rect.west) {
                rect.west = coordinates[0];
            }
            if (coordinates[0] > rect.east) {
                rect.east = coordinates[0];
            }
            if (coordinates[1] < rect.south) {
                rect.south = coordinates[1];
            }
            if (coordinates[1] > rect.north) {
                rect.north = coordinates[1];
            }
        } else if (Array.isArray(coordinates)) {
            for (let i = 0; i < coordinates.length; ++i) {
                this.calculateExtent(coordinates[i], rect);
            }
        }
    }

}

export default VectorData;
